/*
 * @Author: 赵东选 1807248216@qq.com
 * @Date: 2024-10-20 11:42:27
 * @LastEditors: 赵东选 1807248216@qq.com
 * @LastEditTime: 2024-10-20 20:55:44
 * @FilePath: /9_int/bsp/clk/bsp_clk.c
 * @Description:
 *
 * Copyright (c) 2024 by ${git_name_email}, All Rights Reserved.
 */
#include "bsp_clk.h"

/*
 * @description	: 使能I.MX6U所有外设时钟
 * @param 		: 无
 * @return 		: 无
 */
extern void clk_enable(void) {
  CCM->CCGR0 = 0XFFFFFFFF;
  CCM->CCGR1 = 0XFFFFFFFF;
  CCM->CCGR2 = 0XFFFFFFFF;
  CCM->CCGR3 = 0XFFFFFFFF;
  CCM->CCGR4 = 0XFFFFFFFF;
  CCM->CCGR5 = 0XFFFFFFFF;
  CCM->CCGR6 = 0XFFFFFFFF;
}

void imx6u_clkinit() {
  // 初始化6ULL的主频为528MHZ
  uint32_t reg = 0;
  if (((CCM->CCSR >> 2) & 0x1) == 0) {
    // CCM_CCSR_STEP_SEL(0);
    CCM->CCSR &= ~(1 << 8);
    // CCM_CCSR_PLL1_SW_CLK_SEL(1);
    CCM->CCSR |= (1 << 2);
  }

  // 设置PLL1 = 1056MHZ
  reg = CCM_ANALOG->PLL_ARM;
  reg &= ~(0x27f);
  reg |= 0x258;
  // CCM_ANALOG_PLL_ARM_DIV_SELECT(88)
  // CCM_ANALOG_PLL_ARM_ENABLE(1);
  CCM_ANALOG->PLL_ARM = reg;
  // CCM_CDHIPR_ARM_PODF_BUSY(x)
  while ((CCM->CDHIPR >> 16) & 0x1)
    ;
  // CCM_CACRR_ARM_PODF(1);
  CCM->CACRR &= ~(0x7);
  CCM->CACRR = 1; // 设置2分频
  // CCM_CCSR_PLL1_SW_CLK_SEL(x)
  CCM->CCSR &= ~(1 << 2);

  // 设置PLL2的4路PFD
  reg = 0;
  reg = CCM_ANALOG->PFD_528;
  reg &= ~(0x3f3f3f3f);
  // CCM_ANALOG_PFD_528_PFD3_FRAC(0x20)   PLL2_PFD3=297MHZ 528*18/PFD3_FRAC
  reg |= (0x20 << 24);
  // CCM_ANALOG_PFD_528_PFD2_FRAC(0x18)   PLL2_PFD2=396MHZ 528*18/PFD2_FRAC
  reg |= (0x18 << 16);
  // CCM_ANALOG_PFD_528_PFD1_FRAC(0x10)   PLL2_PFD1=594MHZ 528*18/PFD1_FRAC
  reg |= (0x10 << 8);
  // CCM_ANALOG_PFD_528_PFD0_FRAC(0x1b)   PLL2_PFD0=352MHZ 528*18/PFD0_FRAC
  reg |= (0x1b << 0);
  CCM_ANALOG->PFD_528 = reg;

  // 设置PLL3的4路PFD
  reg = 0;
  reg = CCM_ANALOG->PFD_480;
  reg &= ~(0x3f3f3f3f);
  // CCM_ANALOG_PFD_480_PFD3_FRAC(0x13)   PLL3_PFD3=454.7MHZ 480*18/PFD3_FRAC
  reg |= (0x13 << 24);
  // CCM_ANALOG_PFD_480_PFD2_FRAC(0x11)   PLL3_PFD2=508.2MHZ 480*18/PFD2_FRAC
  reg |= (0x11 << 16);
  // CCM_ANALOG_PFD_480_PFD1_FRAC(0x10)   PLL3_PFD1=540MHZ 480*18/PFD1_FRAC
  reg |= (0x10 << 8);
  // CCM_ANALOG_PFD_480_PFD0_FRAC(0xc)   PLL3_PFD0=720MHZ 480*18/PFD0_FRAC
  reg |= (0xc << 0);
  CCM_ANALOG->PFD_480 = reg;

  // 设置其他外设时钟源 AHB_CLK_ROOT PERCLK_CLK_ROOT IPG_CLK_ROOT

  // AHB_CLK_ROOT=132MHZ
  // CCM_CBCMR_PRE_PERIPH_CLK_SEL(0x1)
  CCM->CBCMR &= ~(0x3 << 18);
  CCM->CBCMR |= (0x1 << 18);
  // CCM_CDHIPR_PERIPH_CLK_SEL_BUSY(x)
  while ((CCM->CDHIPR >> 5) & 0x1)
    ;
  // CCM_CBCDR_PERIPH_CLK_SEL(0)
  CCM->CBCDR &= ~(0x1 << 25);
  // CCM_CDHIPR_AHB_PODF_BUSY(x)
  while ((CCM->CDHIPR >> 1) & (0x1))
    ;
  // CCM_CBCDR_AHB_PODF(0x2)
  CCM->CBCDR &= ~(0x7 << 10);
  CCM->CBCDR |= (0x2 << 10);

  // PERCLK_CLK_ROOT=66MHZ IPG_CLK_ROOT=66MHZ
  // CCM_CBCDR_IPG_PODF(0x1)
  CCM->CBCDR &= ~(0x3 << 8);
  CCM->CBCDR |= (0x1 << 8);

  // CCM_CSCMR1_PERCLK_CLK_SEL(0)
  CCM->CSCMR1 &= ~(0x1 << 6);
  // CCM_CSCMR1_PERCLK_PODF(0)
  // CCM->CSCMR1 &= ~(0x3f << 0);
  CCM->CSCMR1 &= ~(0x3f << 0);

  /* 设置UART时钟*/
  CCM->CSCDR1 &= ~(0x1 << 6);
  CCM->CSCDR1 &= ~(0x3f);
}
